package com.ele.client.activity.editor;

import com.ele.client.ClientFactory;
import com.ele.client.activity.editor.widget.GenerateButtonClickEvent;
import com.ele.client.activity.editor.widget.IsEditorWidget;
import com.ele.client.activity.editor.widget.QuestionEditorWidget;
import com.ele.client.activity.editor.widget.WordEditorWidget;
import com.ele.client.rpc.SimpleAsyncCallback;
import com.ele.model.Answer;
import com.ele.model.Question;
import com.ele.model.Section;
import com.ele.model.Word;
import com.github.gwtbootstrap.client.ui.event.ClosedEvent;
import com.github.gwtbootstrap.client.ui.event.ClosedHandler;
import com.google.gwt.activity.shared.AbstractActivity;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.ui.AcceptsOneWidget;

import java.util.ArrayList;
import java.util.List;

public class EditorActivity extends AbstractActivity implements EditorView.Presenter {

    private ClientFactory clientFactory;
    private EditorView view;

    private Long sectionId;

    public EditorActivity(EditorPlace place, ClientFactory clientFactory) {
        this.clientFactory = clientFactory;
        this.sectionId = place.getSectionId();
    }

    @Override
    public void start(AcceptsOneWidget container, EventBus eventBus) {
        view = clientFactory.getEditorView();
        view.setPresenter(this);
        container.setWidget(view.asWidget());

        load();
    }

    @Override
    public void save() {
        Section value = getValue();

        view.startLoading();
        clientFactory.getApplicationService().saveSection(value, new SimpleAsyncCallback<Section>() {
            @Override
            public void onSuccess(Section section) {
                setValue(section);
                view.stopLoading();
            }
        });
    }

    @Override
    public void load() {
        if (sectionId != null) {
            clientFactory.getApplicationService().getSection(sectionId, new SimpleAsyncCallback<Section>() {
                @Override
                public void onSuccess(Section section) {
                    setValue(section);
                }
            });
        } else {
            setValue(null);
        }
    }

    @Override
    public void setValue(Section section) {
        if (section == null) {
            section = new Section();
        }

        view.setName(section.getName());
        view.setDescription(section.getRule());

        view.clearQuestions();
        if (section.getQuestions() != null) {
            for (Question question : section.getQuestions()) {
                addQuestionControl(question);
            }
        }

        view.clearWords();
        if (section.getWords() != null) {
            for (Word word : section.getWords()) {
                addWordControl(word);
            }
        }
    }

    @Override
    public Section getValue() {
        Section section = new Section();
        section.setId(sectionId);

        section.setName(view.getName());
        section.setRule(view.getDescription());
        List<Question> questions = getQuestions();
        for (Question question : questions) {
            question.setSection(section);
        }
        section.setQuestions(questions);
        List<Word> words = getWords();
        for (Word word : words) {
            word.setSection(section);
        }
        section.setWords(words);

        return section;
    }

    @Override
    public void goToNext() {
        clientFactory.getPlaceController().goTo(new EditorPlace(++sectionId));
    }

    @Override
    public void goToPrev() {
        clientFactory.getPlaceController().goTo(new EditorPlace(--sectionId));
    }

    @Override
    public void addBlankQuestion() {
        addQuestionControl(null);
    }

    @Override
    public void addBlankWord() {
        addWordControl(null);
    }

    private List<Question> getQuestions() {
        List<Question> questions = new ArrayList<Question>();
        List<IsEditorWidget<Question>> widgets = view.getQuestionControls();
        for (IsEditorWidget<Question> widget : widgets) {
            questions.add(widget.getValue());
        }
        return questions;
    }

    private List<Word> getWords() {
        List<Word> words = new ArrayList<Word>();
        List<IsEditorWidget<Word>> widgets = view.getWordControls();
        for (IsEditorWidget<Word> widget : widgets) {
            words.add(widget.getValue());
        }
        return words;
    }

    private void addQuestionControl(Question question) {
        final QuestionEditorWidget widget = new QuestionEditorWidget(question);
        widget.addClosedHandler(new ClosedHandler() {
            @Override
            public void onClosed(ClosedEvent closedEvent) {
                view.removeQuestionControl((IsEditorWidget<Question>) closedEvent.getSource());
            }
        });
        widget.addGenerationButtonHandler(new GenerateButtonClickEvent.Handler() {
            @Override
            public void onClick(GenerateButtonClickEvent event) {
                clientFactory.getApplicationService().generateAnswer(event.getQuestionText(), new SimpleAsyncCallback<List<Answer>>() {
                    @Override
                    public void onSuccess(List<Answer> answers) {
                        for (Answer answer : answers) {
                            widget.addAnswerControl(answer);
                        }
                    }
                });
            }
        });
        view.addQuestionControl(widget);
        widget.setFocus(true);
    }

    private void addWordControl(Word word) {
        IsEditorWidget<Word> widget = new WordEditorWidget(word);
        widget.addClosedHandler(new ClosedHandler() {
            @Override
            public void onClosed(ClosedEvent closedEvent) {
                view.removeWordControl((IsEditorWidget<Word>) closedEvent.getSource());
            }
        });
        view.addWordControl(widget);
        widget.setFocus(true);
    }
}
